import { Flow } from '@leafer-in/flow'
import anime from 'animejs'
import { Text } from 'leafer-ui'
import { reactive } from 'vue'
import { uiItems } from './uiItems'

const config = {
    // 元素尺寸
    itemSize: 40,
    // 栈的额外部分高度
    exteraHeight: 30,
    // 动画过渡时间
    duration: 1000,
}

export const stack = reactive({
    size: 10,
    value: [] as any[],
    pushedElements: [] as any[],
    popedElements: [] as any[],
})

// 移动栈顶
const moveZhanding = async () => {
    const index = stack.value.length
    const zhanding = uiItems.zhanding
    if (index === 0) {
        zhanding.opacity = 0
        return
    }
    zhanding.opacity = 1
    const stackHeight = stack.size * config.itemSize
    const y =
        stackHeight - config.itemSize * stack.value.length + config.exteraHeight
    return anime({
        targets: uiItems.zhanding,
        y: y,
        duration: config.duration,
        easing: 'linear',
        update: () => {
            uiItems.zhanding.forceUpdate()
        },
    }).finished
}

const getStackItem = (value: string | number, fill = '#fef08a') => {
    return new Flow({
        x: 75,
        y: -100,
        width: config.itemSize,
        height: config.itemSize,
        fill,
        stroke: '#fff',
        cornerRadius: 50,
        flowAlign: 'center',
        children: [
            new Text({
                text: value,
                fontSize: 20,
            }),
        ],
    })
}

// 入栈
export const push = async (value: string | number) => {
    if (stack.value.length >= stack.size) {
        return
    }
    stack.value.push(value)
    stack.pushedElements.push(value)
    const item = getStackItem(value)
    const cloned = item.clone()
    cloned.fill = '#bbf7d0'
    uiItems.pushContainer.add(cloned)

    const stackContainer = uiItems.stack
    stackContainer.add(item)

    const y =
        (stack.size - stack.value.length) * config.itemSize +
        config.exteraHeight

    const timeline = anime
        .timeline({
            targets: item,
            // update: () => {
            //     item.forceUpdate()
            // },
        })
        .add({
            duration: config.duration * 0.8,
            easing: 'easeOutQuart',
            y,
        })
        .add(
            {
                width: 200,
                cornerRadius: 0,
                duration: config.duration * 0.2,
                easing: 'linear',
                x: 0,
                // y,
                fill: '#fff',
                stroke: '#93c5fd',
            },
            '-=600'
        )

    return Promise.all([timeline.finished, moveZhanding()])
}

// 出栈
export const pop = async () => {
    if (!uiItems.stack || !uiItems.stack.children) return
    const topItem = uiItems.stack.children.at(stack.value.length - 1)
    if (!topItem) return

    const popedValue = stack.value.pop()
    stack.popedElements.push(popedValue)
    uiItems.popContainer.add(getStackItem(popedValue, '#fecaca'))

    const timeline = anime
        .timeline({
            targets: topItem,
        })
        .add({
            y: '-=100',
            duration: config.duration * 0.2,
            easing: 'linear',
        })
        .add({
            y: -100,
            x: 75,
            width: config.itemSize,
            cornerRadius: 50,
            duration: config.duration * 0.8,
            easing: 'easeOutQuart',
        })
    await Promise.all([timeline.finished, moveZhanding()])
    // uiItems.stack.children.splice(uiItems.stack.children.length - 1, 1)
    topItem.remove()
    return
}

// 初始化
export const initStack = (stackSize = 10) => {
    const stackHeight = stackSize * config.itemSize
    const stackUi = uiItems.stack

    // 设置栈的高度
    stackUi.height = stackHeight + config.exteraHeight

    // 清空入栈出栈区域
    const pushContainer = uiItems.pushContainer as Flow
    pushContainer.clear()
    const popContainer = uiItems.popContainer as Flow
    popContainer.clear()

    // 初始化栈
    stack.value = []
    stack.size = stackSize
    stack.popedElements = []
    stack.pushedElements = []

    // 设置栈底栈顶指针的y值
    const { zhandi } = uiItems
    zhandi.y = stackHeight - config.itemSize + config.exteraHeight
    // zhanding.y = stackHeight - config.itemSize + config.exteraHeight

    moveZhanding()
}
